package org.hgvc.webapp.ets.spring.service;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang.StringUtils;
import org.hgvc.webapp.ets.bo.ActionBulletin;
import org.hgvc.webapp.ets.bo.Agent;
import org.hgvc.webapp.ets.bo.Agreement;
import org.hgvc.webapp.ets.bo.CalendarDtl;
import org.hgvc.webapp.ets.bo.ComplimentaryBooking;
import org.hgvc.webapp.ets.bo.EntitlementLookUpTable;
import org.hgvc.webapp.ets.bo.Member;
import org.hgvc.webapp.ets.bo.MemberBooking;
import org.hgvc.webapp.ets.bo.MemberPointEntitle;
import org.hgvc.webapp.ets.bo.Package;
import org.hgvc.webapp.ets.bo.PackagePeakRates;
import org.hgvc.webapp.ets.bo.RCIBooking;
import org.hgvc.webapp.ets.bo.RCIBookingDetail;
import org.hgvc.webapp.ets.bo.VoucherEntryDetail;
import org.hgvc.webapp.ets.constant.ActionBulletinConstant;
import org.hgvc.webapp.ets.constant.AdminConstant;
import org.hgvc.webapp.ets.constant.BookingConstant;
import org.hgvc.webapp.ets.constant.CommonConstant;
import org.hgvc.webapp.ets.constant.MemberConstant;
import org.hgvc.webapp.ets.constant.PartnerConstant;
import org.hgvc.webapp.ets.constant.SystemConstant;
import org.hgvc.webapp.ets.jsf.beans.admin.AdminMemberBookingBean;
import org.hgvc.webapp.ets.spring.dao.BookingHbmDao;
import org.hgvc.webapp.ets.spring.dao.MasterSetupHbmDao;
import org.hgvc.webapp.ets.spring.dao.MemberHbmDao;
import org.hgvc.webapp.ets.spring.dao.PackageHbmDao;
import org.hgvc.webapp.ets.spring.dao.PartnerHbmDao;
import org.jocsb.base.exception.BaseException;
import org.jocsb.base.util.DateUtil;
import org.jocsb.base.util.SpringUtils;
import org.jocsb.base.util.SystemUtil;


public class Copy_2_of_BookingServiceImpl implements BookingService{
	private BookingHbmDao dao;
	private PackageHbmDao packageDao;
	private PartnerHbmDao partnerDao;
	private AdminService adminService;
	private MemberService memberService;
	private SystemService systemService;
	private String normalPeakType;
	private String superPeakType;

	public void setSystemService(SystemService systemService) {
		this.systemService = systemService;
	}
	public void setNormalPeakType(String normalPeakType) {
		this.normalPeakType = normalPeakType;
	}
	public void setSuperPeakType(String superPeakType) {
		this.superPeakType = superPeakType;
	}
	public void setPackageDao(PackageHbmDao packageDao) {
		this.packageDao = packageDao;
	}
	public void setPartnerDao(PartnerHbmDao partnerDao) {
		this.partnerDao = partnerDao;
	}
	public void setDao(BookingHbmDao dao) {
		this.dao = dao;
	}
	public void setAdminService(AdminService adminService) {
		this.adminService = adminService;
	}
	public void setMemberService(MemberService memberService) {
		this.memberService = memberService;
	}
	
	public List<ComplimentaryBooking> getComplimentaryBookingList()throws BaseException{
		List<ComplimentaryBooking> list=new ArrayList<ComplimentaryBooking>();
		try{
			list=dao.getComplimentaryBookingList();
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.object", new Object[]{ComplimentaryBooking.class.getSimpleName()}));
		}
		return list;
	}
	
	public List<ComplimentaryBooking> getComplimentaryBookingList(String searchField,String searchKeyword)throws BaseException{
		List<ComplimentaryBooking> list=new ArrayList<ComplimentaryBooking>();
		try{
			list=dao.getComplimentaryBookingList(searchField,searchKeyword);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.object", new Object[]{ComplimentaryBooking.class.getSimpleName()}));
		}
		return list;
	}
	
	public void saveComplimentaryBooking(ComplimentaryBooking complimentaryBooking)throws BaseException{
		try{
			String bookingNo=adminService.getDocumentNo(CommonConstant.DOC_TYPE_COMPLIMENTARY_BOOKING);
			VoucherEntryDetail voucherEntryDetail = (VoucherEntryDetail)dao.getObject(VoucherEntryDetail.class, complimentaryBooking.getVoucherEntryDetail().getVoucherEntryDetailId());
			complimentaryBooking.setVoucherEntryDetail(voucherEntryDetail);
			complimentaryBooking.setBookingNo(bookingNo);
			complimentaryBooking.setBookingDate(new Date());
			///complimentaryBooking.setStatus(BookingConstant.STATUS_PENDING);
			
			if (complimentaryBooking.getStatus().equalsIgnoreCase(BookingConstant.STATUS_CONFIRM)){
				voucherEntryDetail.setComplimentaryBookingNo(bookingNo);
				voucherEntryDetail.setModifiedBy(complimentaryBooking.getCreatedBy());
				voucherEntryDetail.setModifiedDate(new Date());
				dao.update(voucherEntryDetail);
			}
			dao.save(complimentaryBooking);
		}catch(BaseException be){
			throw be;
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.save.object", new Object[]{ComplimentaryBooking.class.getSimpleName()}));
		}
	}
	
	public void updateComplimentaryBooking(ComplimentaryBooking complimentaryBooking)throws BaseException{
		try{
			if (complimentaryBooking.getStatus().equalsIgnoreCase(BookingConstant.STATUS_CONFIRM)){
				VoucherEntryDetail voucherEntryDetail = (VoucherEntryDetail)dao.getObject(VoucherEntryDetail.class, complimentaryBooking.getVoucherEntryDetail().getVoucherEntryDetailId());
				voucherEntryDetail.setComplimentaryBookingNo(complimentaryBooking.getBookingNo());
				voucherEntryDetail.setModifiedBy(complimentaryBooking.getModifiedBy());
				voucherEntryDetail.setModifiedDate(new Date());
				dao.update(voucherEntryDetail);
			}
			dao.update(complimentaryBooking);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.update.object", new Object[]{ComplimentaryBooking.class.getSimpleName()}));
		}
	}
	
	public void saveRCIBooking(RCIBooking rciBooking)throws BaseException{
		try{
			String bookingNo=adminService.getDocumentNo(CommonConstant.DOC_TYPE_RCI_BOOKING);
			
			rciBooking.setRciBookingNo(bookingNo);
			rciBooking.setRciBookingDate(new Date());
			//rciBooking.setStatus(BookingConstant.STATUS_PENDING);
			dao.save(rciBooking);
		}catch(BaseException be){
			throw be;
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.save.object", new Object[]{RCIBooking.class.getSimpleName()}));
		}
	}
	
	public void updateRCIBooking(RCIBooking rciBooking)throws BaseException{
		try{
			dao.update(rciBooking);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.update.object", new Object[]{RCIBooking.class.getSimpleName()}));
		}
	}
	
	public void saveRCIBookingDetail(RCIBookingDetail rciBookingDetail)throws BaseException{
		try{
			dao.save(rciBookingDetail);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.save.object", new Object[]{RCIBookingDetail.class.getSimpleName()}));
		}
	}
	
	public void updateRCIBookingDetail(RCIBookingDetail rciBookingDetail)throws BaseException{
		try{
			dao.update(rciBookingDetail);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.update.object", new Object[]{RCIBookingDetail.class.getSimpleName()}));
		}
	}
	
	public void deleteRCIBookingDetail(List<RCIBookingDetail> deleteList)throws BaseException{
		try{
			for (RCIBookingDetail rciBookingDetail : deleteList){
				if (rciBookingDetail.isMarkAsSelect()){
					rciBookingDetail.setIsDeleted(CommonConstant.IS_DELETED);
					dao.update(rciBookingDetail);
				}
			}
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.delete.object", new Object[]{RCIBookingDetail.class.getSimpleName()}));
		}
	}
	
	public List<RCIBooking> getRCIBookingList()throws BaseException{
		List<RCIBooking> list=new ArrayList<RCIBooking>();
		try{
			list=dao.getRCIBookingList();
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.object", new Object[]{RCIBooking.class.getSimpleName()}));
		}
		return list;
	}
	
	public List<RCIBookingDetail> getRCIBookingDetailList(RCIBooking rciBooking)throws BaseException{
		List<RCIBookingDetail> list=new ArrayList<RCIBookingDetail>();
		try{
			list=dao.getRCIBookingDetailList(rciBooking);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.object", new Object[]{RCIBookingDetail.class.getSimpleName()}));
		}
		return list;
	}
	
	
	public List<MemberBooking> getMemberBookingList(String bookingStatus)throws BaseException{
		List<MemberBooking> list = new ArrayList<MemberBooking>();
		try{
			list=dao.getMemberBookingList(bookingStatus);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.object", new Object[]{MemberBooking.class.getSimpleName()}));
		}
		return list;
	}
	
	public List<MemberBooking> getMemberBookingList(Agent agent, String bookingStatus)throws BaseException{
		List<MemberBooking> list = new ArrayList<MemberBooking>();
		try{
			list=dao.getMemberBookingList(agent,bookingStatus);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.object", new Object[]{MemberBooking.class.getSimpleName()}));
		}
		return list;
	}
	
	public List<MemberBooking> getMemberBookingList(Member member, String bookingStatus)throws BaseException{
		List<MemberBooking> list = new ArrayList<MemberBooking>();
		try{
			list=dao.getMemberBookingList( member  ,bookingStatus);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.object", new Object[]{MemberBooking.class.getSimpleName()}));
		}
		return list;
	}
	
	public List<MemberBooking> getMemberBookingList(String searchField,String searchKeyword,String bookingStatus)throws BaseException{
		List<MemberBooking> list = new ArrayList<MemberBooking>();
		try{
			list=dao.getMemberBookingList(searchField,searchKeyword,bookingStatus);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.object", new Object[]{MemberBooking.class.getSimpleName()}));
		}
		return list;
	}
	
	public List<MemberBooking> getMemberBookingList(Agent agent,String searchField,String searchKeyword,String bookingStatus)throws BaseException{
		List<MemberBooking> list = new ArrayList<MemberBooking>();
		try{
			list=dao.getMemberBookingList(agent, searchField,searchKeyword,bookingStatus);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.object", new Object[]{MemberBooking.class.getSimpleName()}));
		}
		return list;
	}
	
	public List<MemberBooking> getMemberBookingList(Member member,String searchField,String searchKeyword,String bookingStatus)throws BaseException{
		List<MemberBooking> list = new ArrayList<MemberBooking>();
		try{
			list=dao.getMemberBookingList(member, searchField,searchKeyword,bookingStatus);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.list.object", new Object[]{MemberBooking.class.getSimpleName()}));
		}
		return list;
	}
	
	//Added by Jimmy for Booking
	public void saveApprovePendingFinance(MemberBooking memberBooking, String actionNo) throws Exception {

		if (BookingConstant.STATUS_PENDING_FINANCE.equalsIgnoreCase(memberBooking.getStatus())){
			systemService.deleteActionBulletinByActionNo(actionNo);
			//Insert ActionBulletin to partner about cash
			ActionBulletin ab = new ActionBulletin();
			ab.setActionCode("New member booking no." +memberBooking.getMemberBookingNo() + " is pending for your approval.");
			ab.setCreatedBy(SystemConstant.SYSTEM_USER);
			ab.setCreatedDate(new Date());
			ab.setActionParam1(memberBooking.getMemberBookingId());
			ab.setActionBean(AdminMemberBookingBean.BEAN_NAME);
			ab.setActionMethod(AdminMemberBookingBean.AB_ACTION_INVOKE);
			ab.setIsDeleted(CommonConstant.NOT_DELETED);
			ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
			ab.setActionNo(SystemUtil.getUniqueCode());
			systemService.createActionBulletinByUser(ab, memberBooking.getBookingPackage().getPartner().getRefUser());
			
			memberBooking.setStatus(BookingConstant.STATUS_PENDING);
			MemberBooking dbMemberBooking = (MemberBooking)dao.getObject(MemberBooking.class, memberBooking.getMemberBookingId());
			memberBooking = dbMemberBooking;
			dao.update(memberBooking);
		}
	}
	
	private MasterSetupHbmDao masterSetupHbmDao;
	private MemberHbmDao memberHbmDao;
	public void setMemberHbmDao(MemberHbmDao memberHbmDao) {
		this.memberHbmDao = memberHbmDao;
	}
	public void setMasterSetupHbmDao(MasterSetupHbmDao masterSetupHbmDao) {
		this.masterSetupHbmDao = masterSetupHbmDao;
	}

	public static boolean isBetweenDate(Date date, Date startDate, Date endDate) {
		Date clonedDate = (Date) date.clone();
		clonedDate = DateUtil.formatDateByTime(clonedDate, 0, 0, 0, 0);

		Date clonedStartDate = (Date) startDate.clone();
		Date clonedEndDate = (Date) endDate.clone();

		clonedStartDate = DateUtil.formatDateByTime(clonedStartDate, 0, 0, 0, 0);
		clonedEndDate = DateUtil.formatDateByTime(clonedEndDate, 23, 59, 59, 999);

		return (clonedDate.equals(clonedStartDate) || clonedDate.after(clonedStartDate))
				&& (clonedDate.equals(clonedEndDate) || clonedDate.before(clonedEndDate));
	}
	public static Date addDate(Date date, int noOfDays) {
		Calendar cal = DateUtil.setTime(date);
		cal.add(Calendar.DATE, noOfDays);
		return cal.getTime();
	}
	
	public List<EntitlementLookUpTable> getEntitlementLookUpTables(String memberId) throws Exception{
		List<MemberPointEntitle> memberPointEntitles = memberHbmDao.getValidMemberPointEntitleList(memberId);
		Set<EntitlementLookUpTable> entitlementLookUpTables = new HashSet<EntitlementLookUpTable>();
		MemberPointEntitle previousEntitlement;
		boolean matched = false;
		for(MemberPointEntitle memberPointEntitle : memberPointEntitles){
			for(MemberPointEntitle memberPointEntitleOther : memberPointEntitles){
				if ( memberPointEntitle.getAgreement().getAgreetmentNo().equalsIgnoreCase(memberPointEntitleOther.getAgreement().getAgreetmentNo()) 
						&& memberPointEntitle.getYear().intValue() == memberPointEntitleOther.getYear().intValue()
						&& !memberPointEntitleOther.getPointCategory().getCode().equalsIgnoreCase(
								memberPointEntitle.getPointCategory().getCode())){
					EntitlementLookUpTable entitlementLookUpTable= new EntitlementLookUpTable();
					entitlementLookUpTable.setAgreementNo(memberPointEntitle.getAgreement().getAgreetmentNo());
					entitlementLookUpTable.setYear(memberPointEntitle.getYear());
					if (memberPointEntitle.getPointCategory().getCode().equalsIgnoreCase("GOLD")){
						entitlementLookUpTable.setGoldPoint(memberPointEntitle.getPoint());
						entitlementLookUpTable.setSilverPoint(memberPointEntitleOther.getPoint());
					}else{
						entitlementLookUpTable.setGoldPoint(memberPointEntitleOther.getPoint());
						entitlementLookUpTable.setSilverPoint(memberPointEntitle.getPoint());
					}
					matched = true;
					entitlementLookUpTables.add(entitlementLookUpTable);
					break;
				}
			}
			if (!matched ){
				EntitlementLookUpTable entitlementLookUpTable= new EntitlementLookUpTable();
				entitlementLookUpTable.setAgreementNo(memberPointEntitle.getAgreement().getAgreetmentNo());
				entitlementLookUpTable.setYear(memberPointEntitle.getYear());
				if (memberPointEntitle.getPointCategory().getCode().equalsIgnoreCase("GOLD")){
					entitlementLookUpTable.setGoldPoint(memberPointEntitle.getPoint());
				}else{
					entitlementLookUpTable.setSilverPoint(memberPointEntitle.getPoint());
				}
				matched = true;
				entitlementLookUpTables.add(entitlementLookUpTable);
				break;
			}
		}
		
		return new ArrayList<EntitlementLookUpTable>(entitlementLookUpTables);
	}
	
	public boolean isDayTypePeakPeriod(List<CalendarDtl> calendarDtls,Date inDate){
		SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE");
		for(CalendarDtl calendarDtl : calendarDtls){
			if (PartnerConstant.PARTNER_PRODUCT_PEAK_SEASON.equalsIgnoreCase(calendarDtl.getSeason())
					&& PartnerConstant.PARTNER_CAL_TYPE_DAY.equalsIgnoreCase(calendarDtl.getType()  )
					&& calendarDtl.getDay().equalsIgnoreCase( dateFormat.format(inDate) )) {
				return true;
			}
		}
		return false;
	}
	public void saveMemberBooking(MemberBooking memberBooking)throws BaseException{
		 
		try{
			
			String bookingNo=adminService.getDocumentNo(CommonConstant.DOC_TYPE_MEMBER_BOOKING);
			memberBooking.setMemberBookingNo(bookingNo);
			memberBooking.setMemberBookingDate(new Date());
			Date endBookingDate = addDate(memberBooking.getCheckOutDate(), -1);
//			if (memberBooking.getStatus().equalsIgnoreCase(BookingConstant.STATUS_CONFIRM)){
//				this.memberService.deductMemberPoint(memberBooking.getAgreement().getAgreementId(), memberBooking.getBookingPoint());
//			}
			Package bookingPackage=(Package) dao.getObject(Package.class, memberBooking.getBookingPackage().getPackageId());
			
			//check for date expired date
			bookingPackage.setExpiryDate(DateUtil.formatDateByTime(bookingPackage.getExpiryDate(),0,0,0,0));
			if (bookingPackage.getExpiryDate().before(endBookingDate)){
				throw new BaseException("Your entitlement is expired in " + DateUtil.formatDate(bookingPackage.getExpiryDate(), "dd/MM/yyyy")); 
			}
			//////////////////////
			
			//cannot book more than 6 months in advance
			
			Calendar calendar = Calendar.getInstance();
			calendar.add(Calendar.MONTH, 6);
			if (calendar.getTime().before(memberBooking.getCheckInDate())){
				throw new BaseException("Check-In date must be within 6 months."); 
			}
			//////////
			
			if(memberBooking.getCheckInDate().before(new Date())){
				throw new BaseException("Check-In date is past."); 
			}
			
			////
			//get point or cost
			int weekdayPoint=0;//weekday point term in package setting there. charge to gold or silver is base in package point category later.
			int weekendPoint=0;
			double cost=0;
			boolean match = false;
			List<CalendarDtl> calendarDtls = masterSetupHbmDao.getCalendarDtlByDateType(bookingPackage.getCalendarCat().getCalendarCatId(),
					DateUtil.formatDateByTime(memberBooking.getCheckInDate(),0,0,0,0) ,
					DateUtil.formatDateByTime(memberBooking.getCheckOutDate(),23,59,59,999));
			Date startDate = memberBooking.getCheckInDate();
			List<PackagePeakRates> packagePeakRates = masterSetupHbmDao.getPackagePeakRates(bookingPackage.getPackageId(), "sps");

			 while(isBetweenDate(startDate, memberBooking.getCheckInDate(), endBookingDate)){
				match  = false;
				//look for date type
				for(CalendarDtl calendarDtl : calendarDtls){
					if (PartnerConstant.PARTNER_CAL_TYPE_DATE.equalsIgnoreCase(calendarDtl.getType() ) &&
							isBetweenDate(calendarDtl.getCalDate(), startDate, startDate)
							){
						if (PartnerConstant.PARTNER_PRODUCT_PEAK_SEASON.equalsIgnoreCase(calendarDtl.getSeason())){
							weekendPoint = weekendPoint + bookingPackage.getWeekendPoint();
							cost = cost + bookingPackage.getWeekendPrice();
							match = true;
							break;
						}else if (PartnerConstant.PARTNER_PRODUCT_SUPER_PEAK_SEASON.equalsIgnoreCase(calendarDtl.getSeason())){
							if (packagePeakRates.size()>0){
								if (isDayTypePeakPeriod(calendarDtls, calendarDtl.getCalDate())){
									weekendPoint = weekendPoint + packagePeakRates.get(0).getPoint();
								}else{
									weekdayPoint = weekdayPoint + packagePeakRates.get(0).getPoint();
								}
								cost = cost + packagePeakRates.get(0).getPrice();
							}
							match = true;
							break;
						}
					}
				}
				// look for day type
				if (match == false){
					SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE");
					for(CalendarDtl calendarDtl : calendarDtls){
					 
						if (PartnerConstant.PARTNER_CAL_TYPE_DAY.equalsIgnoreCase(calendarDtl.getType()) && 
								dateFormat.format(startDate).equalsIgnoreCase( calendarDtl.getDay())){
							if (PartnerConstant.PARTNER_PRODUCT_PEAK_SEASON.equalsIgnoreCase(calendarDtl.getSeason())){								
								weekendPoint = weekendPoint + bookingPackage.getWeekendPoint();
								cost = cost + bookingPackage.getWeekendPrice();
								match = true;
								break;
							}else if (PartnerConstant.PARTNER_PRODUCT_SUPER_PEAK_SEASON.equalsIgnoreCase(calendarDtl.getSeason())){
								throw new BaseException("There is "+PartnerConstant.PARTNER_PRODUCT_SUPER_PEAK_SEASON + " for date "+ calendarDtl.getCalDate());
							}
						}
					}
				}
				if (!match){
					weekdayPoint = weekdayPoint + bookingPackage.getWeekdayPoint();
					cost = cost + bookingPackage.getWeekdayPrice();
				}
				startDate = addDate(startDate, 1);
			}
			
			////
			
//			Integer pointToDeduct=0;
//			String checkDay = DateUtil.getDayName(memberBooking.getCheckInDate());
//			if (checkDay.equalsIgnoreCase(DateUtil.DAY_FRI)||checkDay.equalsIgnoreCase(DateUtil.DAY_SAT)){//Detect as Weekend (FRI,SAT)
//				pointToDeduct = bookingPackage.getWeekendPoint();
//			}else{//Weekday(SUN,MON,TUE,WED,THU)
//				pointToDeduct = bookingPackage.getWeekdayPoint();
//			}
//			memberBooking.setBookingPoint(pointToDeduct);
//			memberBooking.setBookingPrice(0.0);
//			dao.save(memberBooking);
			
			 weekendPoint = weekendPoint * memberBooking.getNoRoom();
			 weekdayPoint = weekdayPoint * memberBooking.getNoRoom();
			 cost = cost * memberBooking.getNoRoom();

				memberBooking.setAgreement(memberHbmDao.getAgreementByAgreeNo(memberBooking.getAgreementNo()));

				
			if (AdminConstant.CHARGE_POINT_N_CASH.equalsIgnoreCase(bookingPackage.getChargeType()) && BookingConstant.BOOKING_PAY_BY_CASH.equalsIgnoreCase(memberBooking.getPayBy())){
				memberBooking.setBookingPoint(0);
				memberBooking.setWeekdayPoint(0);
				memberBooking.setWeekendPoint(0);
				memberBooking.setBookingPrice(cost);
				memberBooking.setStatus(BookingConstant.STATUS_PENDING_FINANCE);//let finance approve fist.
				dao.save(memberBooking);

				//Insert ActionBulletin to finance about cash. pending_finance
				ActionBulletin abf = new ActionBulletin();
				abf.setActionCode("Member "+memberBooking.getMember().getName() +" membership "+ memberBooking.getMember().getMembershipNo()+ " cash booking is pending for your approval.");
				abf.setCreatedBy(SystemConstant.SYSTEM_USER);
				abf.setCreatedDate(new Date());
				abf.setActionParam1(memberBooking.getMemberBookingId());
				abf.setActionBean(AdminMemberBookingBean.BEAN_NAME);
				abf.setActionMethod(AdminMemberBookingBean.NAV_VIEW_PENDING_FINANCE);
				abf.setIsDeleted(CommonConstant.NOT_DELETED);
				abf.setType(ActionBulletinConstant.AB_ACK_TYPE);
				abf.setRole(SystemConstant.FINANCE_ADMIN_ROLE);
				abf.setActionNo(SystemUtil.getUniqueCode());
				systemService.createActionBulletinByRoles(abf, SystemConstant.FINANCE_ADMIN_ROLE);
				
			}else{
				String actionNo = SystemUtil.getUniqueCode();
				
				memberBooking.setBookingPoint(weekdayPoint + weekendPoint);//TODO split to 2 column to store
				memberBooking.setWeekdayPoint(weekdayPoint);
				memberBooking.setWeekendPoint(weekendPoint);
				memberBooking.setBookingPrice(0.0);
				memberBooking.setPayBy(BookingConstant.BOOKING_PAY_BY_POINT);
				memberBooking.setActionIdConfirm(actionNo);
				dao.save(memberBooking);
				this.memberService.reserveMemberPoint(bookingPackage, memberBooking.getAgreementNo(),memberBooking.getYear(), weekendPoint,weekdayPoint);
							
				//Insert ActionBulletin to partner
				ActionBulletin ab = new ActionBulletin();
				ab.setActionBean(AdminMemberBookingBean.BEAN_NAME);
				ab.setActionMethod(AdminMemberBookingBean.AB_ACTION_INVOKE);
				ab.setActionCode(SpringUtils.getMessage("ab.new.member.booking.pending.approval", new Object[]{bookingNo}));
				ab.setActionParam1(memberBooking.getMemberBookingId());
				ab.setCreatedBy(SystemConstant.SYSTEM_USER);
				ab.setCreatedDate(new Date());
				ab.setIsDeleted(CommonConstant.NOT_DELETED);
				ab.setType(ActionBulletinConstant.AB_ACTION_TYPE);
				ab.setActionNo(actionNo);
				systemService.createActionBulletinByUser(ab, bookingPackage.getPartner().getRefUser());
				
				
//				//checking done in reserveMemberPoint jo
//				if (memberBooking.getStatus().equalsIgnoreCase(BookingConstant.STATUS_PENDING)){
//					this.memberService.reserveMemberPoint(memberBooking.getAgreement().getAgreementId(), memberBooking.getBookingPoint());
//				}
			}
			
			String newBookingTransactionDesc = SpringUtils.getMessage(MemberConstant.TRANS_NEW_BOOKING, new Object[]{bookingNo,memberBooking.getStatus()});
			memberService.insertMemberTransaction( memberBooking.getAgreementNo(), memberBooking.getYear(), newBookingTransactionDesc);
		}catch(BaseException be){
			throw be;
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.save.object", new Object[]{MemberBooking.class.getSimpleName()}));
		}
	}
	
	public void updateMemberBooking(MemberBooking memberBooking)throws BaseException{
		try{
//			Integer nonPeakPoint=0;
//			Double nonPeakPrice=0.0;
//			String pointCateId="";
//			String checkDay = DateUtil.getDayName(memberBooking.getCheckInDate());
//			if (checkDay.equalsIgnoreCase(DateUtil.DAY_FRI)||checkDay.equalsIgnoreCase(DateUtil.DAY_SAT)){//Detect as Weekend (FRI,SAT)
//				nonPeakPoint = memberBooking.getBookingPackage().getWeekendPoint();
//				nonPeakPrice = memberBooking.getBookingPackage().getWeekendPrice();
//				pointCateId = memberBooking.getBookingPackage().getWePointCate().getPointCatId();
//			}else{//Weekday(SUN,MON,TUE,WED,THU)
//				nonPeakPoint = memberBooking.getBookingPackage().getWeekdayPoint();
//				nonPeakPrice = memberBooking.getBookingPackage().getWeekdayPrice();
//				pointCateId = memberBooking.getBookingPackage().getWdPointCate().getPointCatId();
//			}
//			
			if (memberBooking.getStatus().equalsIgnoreCase(BookingConstant.STATUS_CANCEL)){
				//Cancel Confirm Booking
				MemberBooking dbMemberBooking = (MemberBooking)dao.getObject(MemberBooking.class, memberBooking.getMemberBookingId());
				if (dbMemberBooking.getStatus().equalsIgnoreCase(BookingConstant.STATUS_CONFIRM)){
					
					if (BookingConstant.BOOKING_PAY_BY_POINT.equalsIgnoreCase(memberBooking.getPayBy())){
						memberService.reverseConfirmMemberPoint( memberBooking );
					
					}
					//TODO send message to partner, finance. booking cancel with booking no.	
					//Insert ActionBulletin to partner about cash
					ActionBulletin ab = new ActionBulletin();
					ab.setActionCode("Cancelled Booking ( " +memberBooking.getMemberBookingNo() + ") ." );
					ab.setCreatedBy(SystemConstant.SYSTEM_USER);
					ab.setCreatedDate(new Date());
					ab.setIsDeleted(CommonConstant.NOT_DELETED);
					ab.setType(ActionBulletinConstant.AB_ACK_TYPE);
					ab.setActionNo(SystemUtil.getUniqueCode());
					systemService.createActionBulletinByUser(ab, dbMemberBooking.getBookingPackage().getPartner().getRefUser());
					//Insert ActionBulletin to finance about cash
					ActionBulletin abf = new ActionBulletin();
					abf.setActionCode("Cancelled Booking ( " +memberBooking.getMemberBookingNo() + " ). Total amount RM" + memberBooking.getBookingPrice()+ ".");
					abf.setCreatedBy(SystemConstant.SYSTEM_USER);
					abf.setCreatedDate(new Date());
					abf.setIsDeleted(CommonConstant.NOT_DELETED);
					abf.setType(ActionBulletinConstant.AB_ACK_TYPE);
					abf.setRole(SystemConstant.FINANCE_ADMIN_ROLE);
					abf.setActionNo(SystemUtil.getUniqueCode());
					dao.save(abf);
					
				}else{//cancel penging booking
					if (BookingConstant.BOOKING_PAY_BY_POINT.equalsIgnoreCase(memberBooking.getPayBy()))
						this.memberService.cancelMemberPoint2(memberBooking);
					 
					systemService.deleteActionBulletinByActionNo(memberBooking.getActionIdConfirm());
					
				}
				dbMemberBooking.setModifiedBy(memberBooking.getModifiedBy());
				dbMemberBooking.setConfirmationDate(memberBooking.getConfirmationDate());
				dbMemberBooking.setConfirmationNo(memberBooking.getConfirmationNo());
				dbMemberBooking.setStatus(BookingConstant.STATUS_CANCEL);
				dbMemberBooking.setModifiedDate(new Date());
				memberBooking = dbMemberBooking;
				
				dao.update(dbMemberBooking);
				
			}else{ 
				if (memberBooking.getStatus().equalsIgnoreCase(BookingConstant.STATUS_CONFIRM)){
					if (BookingConstant.BOOKING_PAY_BY_POINT.equalsIgnoreCase(memberBooking.getPayBy()))
						this.memberService.deductMemberPoint2(memberBooking );
					
				}
				dao.update(memberBooking);

				systemService.deleteActionBulletinByActionNo(memberBooking.getActionIdConfirm());
				 
			}

			//Added by Jacky 21-Dec-2008 1201
			String newBookingTransactionDesc = SpringUtils.getMessage(MemberConstant.TRANS_BOOKING, new Object[]{memberBooking.getMemberBookingNo(),memberBooking.getStatus()});
			memberService.insertMemberTransaction( memberBooking.getAgreementNo(), memberBooking.getYear(), newBookingTransactionDesc);
		}catch(BaseException be){
			throw be;
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.update.object", new Object[]{MemberBooking.class.getSimpleName()}));
		}
	}
	//////////////end by jimmy//////////////////
	private void memberPointToDeduct(Agreement agreement,MemberBooking memberBooking,Integer pointToDeduct,String pointCatId,Double nonPeakPrice)throws BaseException{
		try{
			List<MemberPointEntitle> memberPointEntitleList=this.memberService.getMemberPointEntitleList( agreement.getAgreementId(),pointCatId);
			
			if(memberPointEntitleList.size()==0)
				throw new BaseException(SpringUtils.getMessage("error.member.entitlement.not.found",new Object[]{}));	
			
			MemberPointEntitle memberPointEntitle=null;
			memberPointEntitle = memberPointEntitleList.get(0);
			
			Integer availablePoint=memberPointEntitle.getPoint();
			
			if (pointToDeduct<=0)
				throw new BaseException(SpringUtils.getMessage("error.package.deduct.point.not.found",new Object[]{}));
			
			if (availablePoint<pointToDeduct){
				if (memberBooking.getBookingPackage().getChargeType().equalsIgnoreCase(AdminConstant.CHARGE_POINT))
					throw new BaseException(SpringUtils.getMessage("error.member.insufficient.point",new Object[]{}));
				else{
					Integer inSufficentPoint = pointToDeduct - availablePoint;
					Double currentPrice = getPeakPrice(memberBooking, nonPeakPrice);
					Double newChargesPrice = (inSufficentPoint.doubleValue()/pointToDeduct.doubleValue())*currentPrice;
					memberBooking.setBookingPrice(newChargesPrice);
				}
			}
			//Update Member Point
			memberPointEntitle.setPoint(memberPointEntitle.getPoint()-pointToDeduct);
			memberPointEntitle.setModifiedDate(new Date());
			dao.update(memberPointEntitle);
		}catch(BaseException be){
				throw be;
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.update.object", new Object[]{MemberPointEntitle.class.getSimpleName()}));
		}
	}
	
	private void reverseMemberPointDeduction(Agreement agreement,Integer bookingPoint,String pointCatId)throws BaseException{
		try{
			List<MemberPointEntitle> memberPointEntitleList=this.memberService.getMemberPointEntitleList( agreement.getAgreementId(),pointCatId);
			
			/*if(memberPointEntitleList.size()==0)
				throw new BaseException(SpringUtils.getMessage("error.member.entitlement.not.found",new Object[]{}));*/	
			if (memberPointEntitleList.size()>0){
				MemberPointEntitle memberPointEntitle=null;
				memberPointEntitle = memberPointEntitleList.get(0);
				
				//Update Member Point
				memberPointEntitle.setPoint(memberPointEntitle.getPoint()+bookingPoint);
				memberPointEntitle.setModifiedDate(new Date());
				dao.update(memberPointEntitle);	
			}
		}catch(BaseException be){
			throw be;
		}catch(Exception ex){
			
		}
	}
	
	private Integer getPeakPoints(MemberBooking booking,Integer calculatedPoint)throws BaseException{
		Integer peakPoints=0;
		
		try{
			CalendarDtl calendarDtl = this.partnerDao.getCalendarDtl(booking.getBookingPackage().getCalendarCat().getCalendarCatId(), booking.getCheckInDate());
			if (calendarDtl!=null){
				boolean superPeak=false;
				if (calendarDtl.getSeason().equalsIgnoreCase(PartnerConstant.PARTNER_PRODUCT_SUPER_PEAK_SEASON))
					superPeak = true;
				
				PackagePeakRates peakRates = null;
				if (superPeak)
					peakRates = this.packageDao.getPackagePeakRates(booking.getBookingPackage(), this.superPeakType, booking.getCheckInDate());
				else
					peakRates = this.packageDao.getPackagePeakRates(booking.getBookingPackage(), this.normalPeakType, booking.getCheckInDate());
				
				if (peakRates!=null){
					peakPoints = peakRates.getPoint();
				}
					
			}
			if (peakPoints==0)
				peakPoints =  calculatedPoint;
		}catch(Exception ex){
			ex.printStackTrace();
			
		}
		return peakPoints;
	}
	
	private Double getPeakPrice(MemberBooking booking,Double nonPeakPrice)throws BaseException{
		Double peakPrice=0.0;
		
		try{
			CalendarDtl calendarDtl = this.partnerDao.getCalendarDtl(booking.getBookingPackage().getCalendarCat().getCalendarCatId(), booking.getCheckInDate());
			if (calendarDtl!=null){
				boolean superPeak=false;
				if (calendarDtl.getSeason().equalsIgnoreCase(PartnerConstant.PARTNER_PRODUCT_SUPER_PEAK_SEASON))
					superPeak = true;
				
				PackagePeakRates peakRates = null;
				if (superPeak)
					peakRates = this.packageDao.getPackagePeakRates(booking.getBookingPackage(), this.superPeakType, booking.getCheckInDate());
				else
					peakRates = this.packageDao.getPackagePeakRates(booking.getBookingPackage(), this.normalPeakType, booking.getCheckInDate());
				
				if (peakRates!=null){
					peakPrice = peakRates.getPrice();
				}
					
			}
			if (peakPrice==0.0)
				peakPrice =  nonPeakPrice;
		}catch(Exception ex){
			ex.printStackTrace();
			
		}
		return peakPrice;
	}
	
	public MemberBooking getMemberBooking(String memberBookingId)throws BaseException{
		MemberBooking memberBooking = null;
		
		try{
			memberBooking = (MemberBooking)dao.getObject(MemberBooking.class, memberBookingId);
		}catch(Exception ex){
			ex.printStackTrace();
			throw new BaseException(SpringUtils.getMessage("error.invoke.method", new Object[]{"getMemberBooking()"}));
		}
		return memberBooking;
	}

}
